#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
JSON解析工具模块

提供通用的JSON解析功能，用于从LLM响应中提取和验证JSON数据
"""

import json
import re
import logging
from typing import Dict, Any, Optional, List, Callable

logger = logging.getLogger(__name__)


def parse_json_from_text(
    text: str,
    required_fields: Optional[List[str]] = None,
    default_value: Optional[Dict[str, Any]] = None,
    validator: Optional[Callable[[Dict[str, Any]], bool]] = None
) -> Dict[str, Any]:
    """
    从文本中提取并解析JSON
    
    Args:
        text: 包含JSON的文本
        required_fields: 必需的字段列表，用于验证
        default_value: 解析失败时返回的默认值
        validator: 自定义验证函数，接收解析后的字典，返回布尔值
    
    Returns:
        解析后的字典，如果失败则返回default_value
    
    Examples:
        >>> parse_json_from_text('{"name": "test"}', required_fields=["name"])
        {'name': 'test'}
        
        >>> parse_json_from_text('invalid json', default_value={"error": True})
        {'error': True}
    """
    if not text or not text.strip():
        logger.warning("输入文本为空")
        return default_value or {}
    
    try:
        # 尝试多种JSON提取策略
        json_str = _extract_json_string(text)
        
        if not json_str:
            logger.warning("无法从文本中提取JSON")
            return default_value or {}
        
        # 解析JSON
        parsed_data = json.loads(json_str)
        
        # 验证必需字段
        if required_fields and not _validate_required_fields(parsed_data, required_fields):
            logger.warning(f"缺少必需字段: {required_fields}")
            return default_value or {}
        
        # 自定义验证
        if validator and not validator(parsed_data):
            logger.warning("自定义验证失败")
            return default_value or {}
        
        return parsed_data
        
    except json.JSONDecodeError as e:
        logger.warning(f"JSON解析失败: {str(e)}")
        return default_value or {}
    except Exception as e:
        logger.error(f"解析过程中发生错误: {str(e)}")
        return default_value or {}


def _extract_json_string(text: str) -> Optional[str]:
    """
    从文本中提取JSON字符串
    
    尝试多种策略：
    1. 提取代码块中的JSON（markdown格式）
    2. 提取完整的JSON对象（贪婪匹配）
    3. 提取简单的JSON对象（非贪婪匹配）
    """
    # 策略1: 提取代码块中的JSON（markdown格式）
    code_block_match = re.search(r'```(?:json)?\s*(\{[\s\S]*?\})\s*```', text)
    if code_block_match:
        return code_block_match.group(1)
    
    # 策略2: 提取完整的JSON对象（贪婪匹配，支持深层嵌套）
    json_match = re.search(r'\{[\s\S]*\}', text)
    if json_match:
        candidate = json_match.group(0)
        # 验证是否为有效JSON
        try:
            import json
            json.loads(candidate)
            return candidate
        except:
            pass
    
    # 策略3: 提取简单的JSON对象（支持一层嵌套）
    json_match = re.search(r'\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}', text, re.DOTALL)
    if json_match:
        return json_match.group(0)
    
    return None


def _validate_required_fields(data: Dict[str, Any], required_fields: List[str]) -> bool:
    """验证必需字段是否存在"""
    return all(field in data for field in required_fields)


def parse_json_list_from_text(
    text: str,
    default_value: Optional[List[Dict[str, Any]]] = None
) -> List[Dict[str, Any]]:
    """
    从文本中提取并解析JSON数组
    
    Args:
        text: 包含JSON数组的文本
        default_value: 解析失败时返回的默认值
    
    Returns:
        解析后的字典列表，如果失败则返回default_value
    """
    if not text or not text.strip():
        logger.warning("输入文本为空")
        return default_value or []
    
    try:
        # 尝试提取JSON数组
        json_match = re.search(r'\[[\s\S]*\]', text)
        if json_match:
            json_str = json_match.group(0)
            parsed_data = json.loads(json_str)
            
            if isinstance(parsed_data, list):
                return parsed_data
        
        logger.warning("无法从文本中提取JSON数组")
        return default_value or []
        
    except json.JSONDecodeError as e:
        logger.warning(f"JSON数组解析失败: {str(e)}")
        return default_value or []
    except Exception as e:
        logger.error(f"解析过程中发生错误: {str(e)}")
        return default_value or []


def safe_json_loads(json_str: str, default_value: Any = None) -> Any:
    """
    安全的JSON加载函数
    
    Args:
        json_str: JSON字符串
        default_value: 解析失败时返回的默认值
    
    Returns:
        解析后的对象，如果失败则返回default_value
    """
    try:
        return json.loads(json_str)
    except (json.JSONDecodeError, TypeError, ValueError) as e:
        logger.warning(f"JSON加载失败: {str(e)}")
        return default_value
